#include "screencapture.h"

ScreenCapture::ScreenCapture(QObject *parent)
    : QObject(parent),
      captureTimer(new QTimer(this)),
      primaryScreen(QGuiApplication::primaryScreen()),
      compressionQuality(70),
      regionWidth(160),
      regionHeight(120),
      diffEncodingEnabled(true),
      frameCount(0)
{
    // 连接定时器信号
    connect(captureTimer, &QTimer::timeout, this, &ScreenCapture::onCaptureTimer);
    
    // 初始化区域
    initializeRegions();
    
    LOG_INFO("屏幕捕获模块初始化完成");
}

ScreenCapture::~ScreenCapture()
{
    stop();
}

void ScreenCapture::start(int fps)
{
    if (captureTimer->isActive()) {
        captureTimer->stop();
    }
    
    if (fps <= 0) {
        LOG_WARNING("无效的帧率设置");
        return;
    }
    
    // 计算捕获间隔
    int interval = 1000 / fps;
    
    // 启动定时器
    captureTimer->start(interval);
    
    LOG_INFO(QString("屏幕捕获已启动，帧率: %1 FPS (间隔: %2 ms)").arg(fps).arg(interval));
}

void ScreenCapture::stop()
{
    if (captureTimer->isActive()) {
        captureTimer->stop();
        LOG_INFO("屏幕捕获已停止");
    }
}

QByteArray ScreenCapture::captureFullScreen(int quality)
{
    QMutexLocker locker(&captureMutex);
    
    if (!primaryScreen) {
        LOG_ERROR("无法获取主屏幕");
        return QByteArray();
    }
    
    // 捕获整个屏幕
    QPixmap pixmap = primaryScreen->grabWindow(0);
    
    // 保存为上一帧
    lastFrame = pixmap.toImage();
    
    // 转换为字节数组
    return compressImage(lastFrame, quality);
}

QByteArray ScreenCapture::captureRegion(const QRect &region, int quality)
{
    QMutexLocker locker(&captureMutex);
    
    if (!primaryScreen) {
        LOG_ERROR("无法获取主屏幕");
        return QByteArray();
    }
    
    // 确保区域在屏幕范围内
    QRect screenRect(0, 0, primaryScreen->size().width(), primaryScreen->size().height());
    QRect captureRect = region.intersected(screenRect);
    
    if (captureRect.isEmpty()) {
        LOG_WARNING("捕获区域为空");
        return QByteArray();
    }
    
    // 捕获指定区域
    QPixmap pixmap = primaryScreen->grabWindow(0, 
        captureRect.x(), captureRect.y(), captureRect.width(), captureRect.height());
    
    // 转换为字节数组
    return compressImage(pixmap.toImage(), quality);
}

QVector<ScreenRegion> ScreenCapture::captureDirtyRegions(int quality)
{
    QMutexLocker locker(&captureMutex);
    
    if (!primaryScreen) {
        LOG_ERROR("无法获取主屏幕");
        return QVector<ScreenRegion>();
    }
    
    // 捕获整个屏幕
    QPixmap pixmap = primaryScreen->grabWindow(0);
    QImage currentFrame = pixmap.toImage();
    
    // 如果是第一帧，则保存整个图像
    if (lastFrame.isNull()) {
        lastFrame = currentFrame;
        
        // 更新所有区域
        for (int i = 0; i < regions.size(); ++i) {
            QRect regionRect = regions[i].rect;
            QImage regionImage = currentFrame.copy(regionRect);
            regions[i].imageData = compressImage(regionImage, quality);
            regions[i].lastUpdated = frameCount;
        }
        
        frameCount++;
        return regions;
    }
    
    // 存储已更新的区域
    QVector<ScreenRegion> dirtyRegions;
    
    // 检查每个区域是否发生变化
    for (int i = 0; i < regions.size(); ++i) {
        QRect regionRect = regions[i].rect;
        
        // 检查区域是否脏（发生变化）
        if (isRegionDirty(regionRect, currentFrame, lastFrame)) {
            // 区域有变化，更新区域数据
            QImage regionImage = currentFrame.copy(regionRect);
            regions[i].imageData = compressImage(regionImage, quality);
            regions[i].lastUpdated = frameCount;
            
            // 添加到脏区域列表
            dirtyRegions.append(regions[i]);
        }
        // 如果区域很久没更新，也强制更新（防止累积误差）
        else if (frameCount - regions[i].lastUpdated > 30) { // 30帧后强制更新
            QImage regionImage = currentFrame.copy(regionRect);
            regions[i].imageData = compressImage(regionImage, quality);
            regions[i].lastUpdated = frameCount;
            
            // 添加到脏区域列表
            dirtyRegions.append(regions[i]);
        }
    }
    
    // 保存当前帧为上一帧
    lastFrame = currentFrame;
    
    // 增加帧计数
    frameCount++;
    
    return dirtyRegions;
}

void ScreenCapture::setCompressionQuality(int quality)
{
    if (quality < 1 || quality > 100) {
        LOG_WARNING(QString("无效的压缩质量: %1，应在1-100之间").arg(quality));
        return;
    }
    
    compressionQuality = quality;
    LOG_INFO(QString("压缩质量已设置为: %1").arg(quality));
}

void ScreenCapture::setRegionSize(int width, int height)
{
    if (width <= 0 || height <= 0) {
        LOG_WARNING("无效的区域大小");
        return;
    }
    
    regionWidth = width;
    regionHeight = height;
    
    // 重新初始化区域
    initializeRegions();
    
    LOG_INFO(QString("区域大小已设置为: %1x%2").arg(width).arg(height));
}

QSize ScreenCapture::getScreenSize() const
{
    if (!primaryScreen) {
        LOG_ERROR("无法获取主屏幕");
        return QSize();
    }
    
    return primaryScreen->size();
}

bool ScreenCapture::isCapturing() const
{
    return captureTimer->isActive();
}

void ScreenCapture::setDiffEncodingEnabled(bool enabled)
{
    diffEncodingEnabled = enabled;
    LOG_INFO(QString("差分编码已%1").arg(enabled ? "启用" : "禁用"));
}

bool ScreenCapture::isDiffEncodingEnabled() const
{
    return diffEncodingEnabled;
}

void ScreenCapture::onCaptureTimer()
{
    // 根据差分编码设置选择捕获方式
    if (diffEncodingEnabled) {
        // 捕获变化区域
        QVector<ScreenRegion> dirtyRegions = captureDirtyRegions(compressionQuality);
        
        if (!dirtyRegions.isEmpty()) {
            emit regionUpdated(dirtyRegions, getScreenSize());
        }
    } else {
        // 捕获整个屏幕
        QByteArray imageData = captureFullScreen(compressionQuality);
        
        if (!imageData.isEmpty()) {
            emit screenUpdated(imageData, getScreenSize());
        }
    }
}

void ScreenCapture::initializeRegions()
{
    QMutexLocker locker(&captureMutex);
    
    // 清空现有区域
    regions.clear();
    
    if (!primaryScreen) {
        LOG_ERROR("无法获取主屏幕");
        return;
    }
    
    QSize screenSize = primaryScreen->size();
    
    // 计算行数和列数
    int cols = (screenSize.width() + regionWidth - 1) / regionWidth;
    int rows = (screenSize.height() + regionHeight - 1) / regionHeight;
    
    // 创建区域
    for (int row = 0; row < rows; ++row) {
        for (int col = 0; col < cols; ++col) {
            int x = col * regionWidth;
            int y = row * regionHeight;
            int width = qMin(regionWidth, screenSize.width() - x);
            int height = qMin(regionHeight, screenSize.height() - y);
            
            QRect rect(x, y, width, height);
            regions.append(ScreenRegion(rect));
        }
    }
    
    LOG_INFO(QString("屏幕已分割为 %1 个区域（%2 行 x %3 列）")
            .arg(regions.size()).arg(rows).arg(cols));
}

bool ScreenCapture::isRegionDirty(const QRect &region, const QImage &current, const QImage &previous)
{
    // 区域像素总数
    int totalPixels = region.width() * region.height();
    if (totalPixels <= 0) {
        return false;
    }
    
    // 抽样检测变化像素
    int sampleSize = qMax(1, totalPixels / 100); // 抽样1%的像素
    int changedPixels = 0;
    
    for (int i = 0; i < sampleSize; ++i) {
        // 随机选择一个像素位置
        int x = region.x() + (qrand() % region.width());
        int y = region.y() + (qrand() % region.height());
        
        // 比较两个图像的像素颜色
        if (current.pixel(x, y) != previous.pixel(x, y)) {
            changedPixels++;
        }
    }
    
    // 计算变化百分比
    double changePercent = (changedPixels * 100.0) / sampleSize;
    
    // 如果变化百分比超过阈值，则认为区域有变化
    return changePercent >= DIRTY_THRESHOLD;
}

QByteArray ScreenCapture::compressImage(const QImage &image, int quality)
{
    if (image.isNull()) {
        LOG_WARNING("压缩空图像");
        return QByteArray();
    }
    
    // 创建字节数组用于存储图像数据
    QByteArray byteArray;
    QBuffer buffer(&byteArray);
    buffer.open(QIODevice::WriteOnly);
    
    // 使用JPEG格式压缩图像
    if (!image.save(&buffer, "JPEG", quality)) {
        LOG_ERROR("图像压缩失败");
        return QByteArray();
    }
    
    buffer.close();
    return byteArray;
} 